//
//  SFNetwork.swift
//  SeeFM_Swift
//
//  Created by CBCT_MBP on 2021/6/1.
//




import UIKit

struct ResponseModel: HandyJSON {
    var m: String?
    var c: Int?
    var d: [String:Any]?
}


/**
 常见的 MIME 类型

 超文本标记语言文本 .html,.html text/html
 普通文本 .txt text/plain
 RTF文本 .rtf application/rtf
 GIF图形 .gif image/gif
 JPEG图形 .ipeg,.jpg image/jpeg
 au声音文件 .au audio/basic
 MIDI音乐文件 mid,.midi audio/midi,audio/x-midi
 RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
 MPEG文件 .mpg,.mpeg video/mpeg
 AVI文件 .avi video/x-msvideo
 GZIP文件 .gz application/x-gzip
 TAR文件 .tar application/x-tar
 */
public struct SFMultipartFormdata {
    public let data: Data?
    public let name: String?
    public let filename: String?
    public let mineType: String?
    
    public init(data: Data?, name: String?, fileName: String?, mineType: String?) {
        self.data = data
        self.name = name
        self.filename = fileName
        self.mineType = mineType
    }
    
    public init(image: UIImage?, name: String?, fileName: String?) {
        self.data = image?.jpegData(compressionQuality: 1)
        self.name = name
        self.filename = fileName
        self.mineType = "image/jpeg"
    }
}

public struct SFSuccess {
    public let data: [String:Any]?
}

public struct SFError {
    public let error: Error?
    public let errMsg: String?
    public let code: Int?
}

enum SFResponse {
    case success(SFSuccess)
    case fail(SFError)
}

typealias SFResponseClosure = (_ result: SFResponse) -> Void
typealias SFProgressBlock = (_ progress: Double) -> Void

enum NetworkStatus {
    case unknown            // 未知网络
    case notReachable       // 网络无连接
    case wwan               // 2/3/4/5G
    case wifi               // WIFI 网络
}
        
class SFNetwork: NSObject {
    static let shared = SFNetwork()
    private var sessionManager: Session?
    var header: HTTPHeaders = [
        "Accept":SFNetBean.shared.jsonFormat(),
        "User-Agent":"iOS|"+SFNetBean.shared.systemVersion()+"|"+SFNetBean.shared.appLFVersion()+"|"+SFNetBean.shared.systemHardwareName()+"|"+SFNetBean.shared.channelName(),
    ]
    
    private override init() {
        super.init()
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 60
        sessionManager = Session.init(configuration: configuration, delegate: SessionDelegate.init())
        
        header.add(name: "X-cbct-dtk", value: "")
        header.add(name: "X-cbct-utk", value: "")
        header.add(name: "X-cbct-slt", value: "")
        header.add(name: "X-cbct-tsm", value: "")
        header.add(name: "X-cbct-sgn", value: "")
        header.add(name: "X-cbct-version", value: "")
        header.add(name: "X-cbct-os", value: "2")
        header.add(name: "host", value: Adapter.Param.get(kind: .api_host))
    }
    
    // GET
    class func get(url: String,
                    params: [String : Any]? = nil,
                    complete: SFResponseClosure?) {
        
        SFNetwork.shared.manageGet(url: url,
                                   params: params,
                                   complete: complete)
    }
    
    // POST
    class func post(url: String,
                    params: [String : Any]? = nil,
                    complete: SFResponseClosure?) {
        
        SFNetwork.shared.managePost(url: url,
                                    params: params,
                                    complete: complete)
    }
    
    // 上传单个文件
    class func upload(url: String,
                       multiPartFormData: SFMultipartFormdata,
                       param: Parameters?,
                       progress: SFProgressBlock?,
                       complete: SFResponseClosure?) {

        let failClosure = {(errMsg: String) in
            let err: SFResponse = SFResponse.fail(SFError(error: nil, errMsg: errMsg, code: 0))
            complete?(err)
        }
        
        guard let _ = multiPartFormData.data else {
            failClosure("请检查图片")
            return }
        guard let _ = multiPartFormData.name else {
            failClosure("请检查name字段")
            return }
        guard let _ = multiPartFormData.filename else {
            failClosure("请检查图片")
            return }
        guard let _ = multiPartFormData.mineType else {
            failClosure("请检查图片")
            return }
        
        SFNetwork.upload(url: url,
                         multiPartFormDatas: [multiPartFormData],
                         param: param,
                         progress: progress,
                         complete: complete)
    }
    
    // 上传多个
    class func upload(url: String,
                       multiPartFormDatas: [SFMultipartFormdata]?,
                       param: Parameters?,
                       progress: SFProgressBlock?,
                       complete: SFResponseClosure?) {
        
        guard let multFormData = multiPartFormDatas else {return}
        
        let formData: ((MultipartFormData)->Void) = { (mfd) in
            if let postParams = param {
                for (k, v) in postParams {
                    mfd.append("\(v)".data(using: .utf8)!, withName: k)
                }
            }
            for part in multFormData {
                mfd.append(part.data ?? Data(),
                           withName: part.name ?? "",
                           fileName: part.filename ?? "",
                           mimeType: part.mineType ?? "")
            }
        }
        
        AF.upload(multipartFormData: formData, to: url,
        method: .post,
        headers: HTTPHeaders()).uploadProgress{(p) in
            
            progress?(p.fractionCompleted)
            
        }.responseJSON {(response) in
            
//            switch response.result {
//
//            case .success(let responseData):
//                if JSONSerialization.isValidJSONObject(responseData) {
//                    success?(responseData as! Dictionary)
//
//                }else {
//                    let err: AFError = AFError.responseSerializationFailed(reason: .invalidEmptyResponse(type: "返回数据为空"))
//                    fail?(err)
//                }
//                break
//
//            case .failure(let err):
//                fail?(err)
//                break
//            }

        }
        
    }
    
    func resetHeaderField(isRegister: Bool) {
        let dtk = isRegister ? "" : Login.isLogin() ? SignManager.getDeviceToken() : SignManager.getToken()
        let utk = isRegister ? "" : Login.isLogin() ? SignManager.getToken() : ""
        let slt = isRegister ? "" : SignManager.getSalt()
        let sgn = isRegister ? SignManager.getRegisterSign() : SignManager.getApiSign()
        let tsm = SignManager.getSignTimeString()
        let vsn = String.init(format: "%@", SFNetBean.appVersion)
        
        header.update(name: "X-cbct-dtk", value: dtk)
        header.update(name: "X-cbct-utk", value: utk)
        header.update(name: "X-cbct-slt", value: slt)
        header.update(name: "X-cbct-tsm", value: tsm)
        header.update(name: "X-cbct-sgn", value: sgn)
        header.update(name: "X-cbct-version", value: vsn)
        
    }
    
    private func manageGet(url: String,
                           params: [String : Any]?,
                           complete: SFResponseClosure?) {
        
        let scheme = Adapter.Param.get(kind: .scheme)
        let host = Adapter.Param.get(kind: .api_host)
        let u = String(format: "%@%@%@", scheme,host,url)
        self.resetHeaderField(isRegister: url == kAPI_register_device || url == kAPI_check_time)
        
        print("SFNetwork: GET请求 url:",u)
        
        AF.request(u,
                   method: .get,
                   parameters: params,
                   headers: header)
            .responseJSON { (response) in
                
                switch response.result {
                
                case .success(let responseData):
                    
                    if JSONSerialization.isValidJSONObject(responseData) {
                        
                        let responseModel = ResponseModel.deserialize(from: responseData as? Dictionary)
                        if responseModel?.c == 200 {
                            complete?(SFResponse.success(SFSuccess(data: responseModel?.d)))
                        }else {
                            complete?(SFResponse.fail(SFError(error: nil, errMsg: responseModel?.m, code: responseModel?.c)))
                        }
                        
                    }else {
                        complete?(SFResponse.fail(SFError(error: nil, errMsg: "数据格式错误", code: 0)))
                    }
                    
                case .failure(let err):
                    complete?(SFResponse.fail(SFError(error: err, errMsg: err.localizedDescription, code: err.responseCode ?? 0)))
                }
            }
    }
    
    private func managePost(url: String,
                            params: [String : Any]?,
                            complete: SFResponseClosure?) {
        let scheme = Adapter.Param.get(kind: .scheme)
        let host   = Adapter.Param.get(kind: .api_host)
        let u = String(format: "%@%@%@", scheme,host,url)
        print("SFNetwork: POST请求 url:",u)
        self.resetHeaderField(isRegister: url == kAPI_register_device || url == kAPI_check_time)
        
        AF.request(u,
                   method: .post,
                   parameters: params,
                   headers: header)
            .responseJSON { (response) in
                
                switch response.result {
                
                case .success(let responseData):
                    
                    if JSONSerialization.isValidJSONObject(responseData) {
                        
                        let responseModel = ResponseModel.deserialize(from: responseData as? Dictionary)
                        if responseModel?.c == 200 {
                            complete?(SFResponse.success(SFSuccess(data: responseModel?.d)))
                        }else {
                            complete?(SFResponse.fail(SFError(error: nil, errMsg: responseModel?.m, code: responseModel?.c)))
                        }
                        
                    }else {
                        complete?(SFResponse.fail(SFError(error: nil, errMsg: "数据格式错误", code: 0)))
                    }
                    
                case .failure(let err):
                    complete?(SFResponse.fail(SFError(error: err, errMsg: err.localizedDescription, code: err.responseCode ?? 0)))
                }
            }
    }
}



